package com.tiantian.web.controller.topic;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.tiantian.common.annotation.Log;
import com.tiantian.common.annotation.RepeatSubmit;
import com.tiantian.common.constant.SystemConfigConstants;
import com.tiantian.common.core.controller.BaseController;
import com.tiantian.common.core.domain.ResponseResult;
import com.tiantian.common.core.domain.dto.AnswerTimeDAO;
import com.tiantian.common.core.page.TableDataInfo;
import com.tiantian.common.enums.BusinessType;
import com.tiantian.common.enums.OperatorType;
import com.tiantian.common.exception.BusinessException;
import com.tiantian.common.utils.DateUtils;
import com.tiantian.common.utils.redis.RedisUtils;
import com.tiantian.topic.domain.entity.SysReplay;
import com.tiantian.topic.domain.entity.SysTopic;
import com.tiantian.topic.service.SysReplyService;
import com.tiantian.topic.service.SysTopicService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * (SysReplay)控制层
 *
 * @author tiantian
 */
@RequiredArgsConstructor
@RestController
@RequestMapping("/reply")
public class SysReplyController extends BaseController {

    private final SysReplyService sysReplyService;
    private final SysTopicService sysTopicService;

    /**
     * 分页查询
     *
     * @param sysReplay 实体筛选条件
     * @return 分页数据
     */
    @GetMapping("/list")
    public TableDataInfo selectPage(SysReplay sysReplay) {
        startPage();
        List<SysReplay> sysReplays = sysReplyService.selectList(sysReplay);
        return getDataTable(sysReplays);
    }

    /**
     * 通过主键查询单条数据
     *
     * @param replyId 主键
     * @return 单条数据
     */
    @GetMapping("/{replyId}")
    public ResponseResult<SysReplay> selectOneById(@PathVariable String replyId) {
        return ResponseResult.ok(sysReplyService.selectById(replyId));
    }

    /**
     * 查询我的答案
     *
     * @param topicId 题目ID
     */
    @GetMapping("/myAns/{topicId}")
    @SaCheckLogin
    public ResponseResult<SysTopic> getMyAns(@PathVariable String topicId) {
        Long userId = getUserId();
        checkReplyUnique(topicId);
        SysTopic sysTopic = sysTopicService.selectById(topicId);
        // 答题模板设置成 [我的答案]
        String ans = sysReplyService.selectAnsByTopicIdAndUserId(topicId, userId);
        sysTopic.setCodeTemplate(ans);
        return ResponseResult.ok(sysTopic);
    }

    /**
     * 修改答案
     *
     * @param sysReplay sysReplay
     */
    @PutMapping("/updateAns")
    @Log(title = "新人修改答案", businessType = BusinessType.NEWCOMER_UPDATE_ANS, operatorType = OperatorType.NEWCOMER, isSaveResponseData = false)
    public ResponseResult<String> updateMyAns(@RequestBody @Valid SysReplay sysReplay) {
        // 判断当前提交时间是否在允许修改范围内
        checkTimeRange();
        String topicId = sysReplay.getTopicId();
        // 判断题目是否存在
        checkTopicExist(topicId);
        // 判断是否有答题记录
        checkReplyUnique(topicId);
        // 设置字段
        sysReplay.setUserId(getUserId());
        setCommonFieldUpdate(sysReplay);

        // 修改答案
        Boolean update = sysReplyService.changAnswer(sysReplay);
        if (BooleanUtil.isTrue(update)) {
            // 返回题目编号
            return ResponseResult.ok("修改成功", sysReplay.getReplyId());
        }
        return ResponseResult.fail("未知异常,提交失败,请联系管理员");
    }

    /**
     * 获取评分细节
     *
     * @return ajax
     */
    @GetMapping("/detail")
    public ResponseResult<Map<String, Object>> getReplyDetail() {
        Map<String, Object> ajax = new HashMap<>();
        // TODO
        ajax.put("judgeInfo", "userInfo");
        ajax.put("topicInfo", "userInfo");
        ajax.put("judgeDetail", "judgeDetail");
        return ResponseResult.ok(ajax);
    }

    /**
     * 提交解题
     *
     * @param sysReplay 实体类
     * @return 提交编号
     */
    @PostMapping("/ans")
    @RepeatSubmit(message = "请勿频繁提交解题")
    @Log(title = "新人提交解题", businessType = BusinessType.NEWCOMER_SUBMIT_TOPIC, operatorType = OperatorType.NEWCOMER, isSaveResponseData = false)
    public ResponseResult<String> addReplay(@RequestBody @Valid SysReplay sysReplay) {
        // 判断当前提交时间是否在允许提交范围内
        checkTimeRange();
        // 判断题目是否存在
        String topicId = sysReplay.getTopicId();
        checkTopicExist(topicId);
        // 判断用户是否已经提交
        Long userId = getUserId();
        if (sysReplyService.checkReplyUnique(topicId, userId) > 0) {
            throw new BusinessException("请勿重复提交该题目");
        }
        // 属性设置
        String replyId = IdUtil.getSnowflakeNextIdStr();
        sysReplay.setReplyId(replyId);
        sysReplay.setScore(-1);
        sysReplay.setUserId(userId);
        // 设置基础字段
        setCommonFieldInsert(sysReplay);
        Boolean insert = sysReplyService.insert(sysReplay);
        if (BooleanUtil.isTrue(insert)) {
            // 返回题目编号
            return ResponseResult.ok("提交成功", replyId);
        }
        return ResponseResult.fail("未知异常,提交失败,请联系管理员");
    }

    /**
     * 检查题目是否存在
     *
     * @param topicId 题目ID
     */
    private void checkTopicExist(String topicId) {
        SysTopic sysTopic = sysTopicService.selectById(topicId);
        if (ObjectUtil.isEmpty(sysTopic)) {
            throw new BusinessException("题目编号不存在, 提交失败");
        }
    }

    /**
     * 检查答题记录是存在
     *
     * @param topicId 题目ID
     */
    private void checkReplyUnique(String topicId) {
        if (sysReplyService.checkReplyUnique(topicId, getUserId()) == 0) {
            throw new BusinessException("您未提交任何解题, 修改答案失败");
        }
    }

    /**
     * 检查提交时间是否符合系统设置的时间
     */
    private void checkTimeRange() {
        // 获取系统设置的时间
        AnswerTimeDAO ansTime = RedisUtils.get(SystemConfigConstants.SYSTEM_CONFIG_ANSWER_TIME_KEY, AnswerTimeDAO.class);
        if (ObjectUtil.isEmpty(ansTime)) {
            throw new BusinessException("答题时间未设置请联系管理员");
        }
        // 获取当前时间
        LocalDateTime localDateTimeNow = DateUtils.getCurrentDateTime();

        // 构造开始时间和结束时间
        LocalDateTime startTime = LocalDateTimeUtil.parse(ansTime.getDate() + " " + ansTime.getStart(), "yyyy-MM-dd HH:mm:ss");
        LocalDateTime endTime = LocalDateTimeUtil.parse(ansTime.getDate() + " " + ansTime.getEnd(), "yyyy-MM-dd HH:mm:ss");

        // 判断是否在答题时间范围内
        if (!(localDateTimeNow.isAfter(startTime) && localDateTimeNow.isBefore(endTime))) {
            throw new BusinessException("当前时间不在答题时间范围内");
        }
    }

}

